package cn.o.app;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.ViewGroup;
import cn.o.app.context.IContextProvider;
import cn.o.app.event.listener.OnActivityResultListener;
import cn.o.app.task.IStopable;
import cn.o.app.task.IStopableManager;
import cn.o.app.ui.IActivityResultCatcher;
import cn.o.app.ui.IActivityStarter;
import cn.o.app.ui.IStateView;
import cn.o.app.ui.IStateViewManager;
import cn.o.app.ui.IToastOwner;
import cn.o.app.ui.OToast;
import cn.o.app.util.ILockable;

public class OWrapper {

	public static void bindStateViews(IStateViewManager manager, View v) {
		bindStateViews(manager, v, 0, Integer.MAX_VALUE);
	}

	public static void bindStateViews(IStateViewManager manager, View v,
			int depth, int maxDepth) {
		if (depth >= maxDepth) {
			return;
		}
		if (v instanceof IStateView) {
			if (v != manager) {
				manager.bind((IStateView) v);
				return;
			}
		}
		if (v instanceof ViewGroup) {
			ViewGroup g = (ViewGroup) v;
			for (int i = 0, size = g.getChildCount(); i < size; i++) {
				bindStateViews(manager, g.getChildAt(i), depth + 1, maxDepth);
			}
		}
	}

	public static void bind(IStateViewManager manager, IStateView v) {
		List<IStateView> views = manager.getBindStateViews();
		if (views.contains(v)) {
			return;
		}
		v.setManager(manager);
		views.add(v);
	}

	public static void bind(IStopableManager manager, IStopable s) {
		List<IStopable> stopables = manager.getBindStopables();
		List<IStopable> stopedList = null;
		for (IStopable stopable : stopables) {
			if (stopable.equals(s)) {
				if (stopedList != null) {
					stopables.removeAll(stopedList);
					stopedList.clear();
				}
				return;
			}
			if (stopable.isStoped()) {
				if (stopedList == null) {
					stopedList = new ArrayList<IStopable>();
				}
				stopedList.add(stopable);
			}
		}
		if (stopedList != null) {
			stopables.removeAll(stopedList);
			stopedList.clear();
		}
		stopables.add(s);
	}

	public static void dispatchCreate(IStateView v) {
		if (v.isCreateDispatched()) {
			return;
		}
		v.onCreate();
		v.setCreateDispatched(true);
	}

	public static void dispatchStart(IStateViewManager manager) {
		if (manager instanceof IStateView) {
			IStateView v = (IStateView) manager;
			if (!v.isCreateDispatched()) {
				dispatchCreate(v);
			}
		}
		if (manager.redirectToSelectedView()) {
			IStateView v = manager.getSelectedView();
			if (v != null) {
				v.onStart();
			}
		} else {
			List<IStateView> views = manager.getBindStateViews();
			for (IStateView stateView : views) {
				stateView.onStart();
			}
		}
	}

	public static void dispatchResume(IStateViewManager manager) {
		if (manager instanceof IStateView) {
			IStateView v = (IStateView) manager;
			if (!v.isCreateDispatched()) {
				v.onStart();
			}
		}
		if (manager.redirectToSelectedView()) {
			IStateView v = manager.getSelectedView();
			if (v != null) {
				v.onResume();
			}
		} else {
			List<IStateView> views = manager.getBindStateViews();
			for (IStateView stateView : views) {
				stateView.onResume();
			}
		}
	}

	public static void dispatchPause(IStateViewManager manager) {
		if (manager instanceof IStateView) {
			IStateView v = (IStateView) manager;
			if (!v.isCreateDispatched()) {
				dispatchCreate(v);
			}
		}
		if (manager instanceof IStopableManager) {
			((IStopableManager) manager).stopAll();
		}
		if (manager.redirectToSelectedView()) {
			IStateView v = manager.getSelectedView();
			if (v != null) {
				v.onPause();
			}
		} else {
			List<IStateView> views = manager.getBindStateViews();
			for (IStateView stateView : views) {
				stateView.onPause();
			}
		}
		if (manager instanceof IToastOwner) {
			OToast toast = ((IToastOwner) manager).getToast();
			if (toast != null) {
				toast.hideNow();
			}
		}
	}

	public static void dispatchStop(IStateViewManager manager) {
		if (manager instanceof IStateView) {
			IStateView v = (IStateView) manager;
			if (!v.isCreateDispatched()) {
				v.onPause();
			}
		}
		if (manager.redirectToSelectedView()) {
			IStateView v = manager.getSelectedView();
			if (v != null) {
				v.onStop();
			}
		} else {
			List<IStateView> views = manager.getBindStateViews();
			for (IStateView stateView : views) {
				stateView.onStop();
			}
		}
	}

	public static void dispatchDestroy(IStateViewManager manager) {
		if (manager instanceof IStateView) {
			IStateView v = (IStateView) manager;
			if (!v.isCreateDispatched()) {
				return;
			}
		}
		if (manager instanceof IStopableManager) {
			((IStopableManager) manager).stopAll(true);
		}
		List<IStateView> views = manager.getBindStateViews();
		for (IStateView stateView : views) {
			stateView.onDestroy();
		}
		views.clear();
	}

	public static void stopAll(IStopableManager manager) {
		stopAll(manager, false);
	}

	public static void stopAll(IStopableManager manager, boolean includeLockable) {
		List<IStopable> stopables = manager.getBindStopables();
		List<IStopable> stopedList = null;
		for (IStopable stopable : stopables) {
			if (includeLockable) {
				if (stopable instanceof ILockable) {
					continue;
				}
			}
			stopable.stop();
			if (stopedList == null) {
				stopedList = new ArrayList<IStopable>();
			}
			stopedList.add(stopable);
		}
		if (stopedList != null) {
			stopables.removeAll(stopedList);
			stopedList.clear();
		}
	}

	public static boolean interceptBackPressed(IStateViewManager manager) {
		if (manager instanceof IStopableManager) {
			List<IStopable> stopables = ((IStopableManager) manager)
					.getBindStopables();
			boolean catchStopableed = false;
			List<IStopable> stopedList = null;
			for (IStopable stopable : stopables) {
				if (stopable instanceof ILockable) {
					continue;
				}
				if (stopable.isStoped()) {
					if (stopedList == null) {
						stopedList = new ArrayList<IStopable>();
					}
					stopedList.add(stopable);
					continue;
				}
				if (!stopable.isRunInBackground() && !stopable.isStoped()) {
					catchStopableed = true;
					stopable.stop();
					if (stopedList == null) {
						stopedList = new ArrayList<IStopable>();
					}
					stopedList.add(stopable);
				}
			}
			if (stopedList != null) {
				stopables.removeAll(stopedList);
				stopedList.clear();
			}
			if (catchStopableed) {
				return true;
			}
		}
		if (manager.redirectToSelectedView()) {
			IStateView v = manager.getSelectedView();
			if (v != null) {
				if (v.onInterceptBackPressed()) {
					return true;
				}
			}
		} else {
			List<IStateView> views = manager.getBindStateViews();
			for (IStateView stateView : views) {
				if (stateView.onInterceptBackPressed()) {
					return true;
				}
			}
		}
		return false;
	}

	public static void startActivity(IContextProvider contextProvider,
			Intent intent) {
		contextProvider.getContext().startActivity(intent);
	}

	public static void startActivityForResult(IActivityStarter activityStarter,
			Intent intent, int requestCode) {
		Context context = activityStarter.getContext();
		if (context instanceof Activity) {
			((Activity) context).startActivityForResult(intent, requestCode);
		}
	}

	public static void onActivityResult(
			IActivityResultCatcher activityResultCatcher, int requestCode,
			int resultCode, Intent data) {
		List<OnActivityResultListener> listeners = activityResultCatcher
				.getOnActivityResultListeners();
		if (listeners != null) {
			for (OnActivityResultListener listener : listeners) {
				listener.onActivityResult(activityResultCatcher.getContext(),
						requestCode, resultCode, data);
			}
		}
		if (!(activityResultCatcher instanceof IStateViewManager)) {
			return;
		}
		IStateViewManager manager = (IStateViewManager) activityResultCatcher;
		if (manager.redirectToSelectedView()) {
			IStateView selectedView = manager.getSelectedView();
			if (selectedView == null) {
				return;
			}
			selectedView.onActivityResult(requestCode, resultCode, data);
		} else {
			List<IStateView> bindViews = manager.getBindStateViews();
			if (bindViews == null) {
				return;
			}
			for (IStateView stateView : bindViews) {
				stateView.onActivityResult(requestCode, resultCode, data);
			}
		}
	}
}
